﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Win32;

namespace CloudClip.ExtensionMethod
{
    public static class FileExtension
    {
        #region 檔案操作

        public static DirectoryInfo GetDirectory(this string sFilePath)
        {
            FileInfo fileInfo = new FileInfo(sFilePath);
            return fileInfo.Directory;
        }

        public static void CreateFolder(this string sFilePath)
        {
            if (sFilePath.IndexOf(".") == -1)
            {
                //代表傳入為目錄，隨便造一個File給他造Folder
                sFilePath += @"\Test123.txt";
            }

            FileInfo fileInfo = new FileInfo(sFilePath);

            if (fileInfo.Directory.Exists == false)
                fileInfo.Directory.Create();
        }

        public static void CreateFile(string sFileName, string sContent)
        {
            FileInfo fileInfo = new FileInfo(sFileName);
            CreateFolder(sFileName);

            StreamWriter streamWriter = new StreamWriter(fileInfo.FullName, true);
            streamWriter.Write(sContent);
            streamWriter.Close();
        }

        public static FileInfo GetFileInfo(this string sFilePath)
        {
            FileInfo fileInfo = new FileInfo(sFilePath);

            if (fileInfo.Exists == false)
            {
                throw new Exception("檔案不存在 FilePath:" + sFilePath);
            }

            return fileInfo;
        }

        public static void CopyTo(this string sFilePath, string sTargetPath)
        {
            if (PathEqual(sFilePath, sTargetPath))
            {
                //重覆就不移動
                return;
            }

            CreateFolder(sTargetPath);

            FileInfo fileInfo = GetFileInfo(sFilePath);
            ForceDeleteFile(sTargetPath);
            fileInfo.CopyTo(sTargetPath);
        }

        public static void MoveTo(this string sFilePath, string sTargetPath)
        {
            MoveTo(sFilePath, sTargetPath, false);
        }

        public static void MoveTo(this string sFilePath, string sTargetPath, bool bAlwayMove)
        {
            if (PathEqual(sFilePath, sTargetPath) && !bAlwayMove)
            {
                //重覆就不移動
                return;
            }

            CreateFolder(sTargetPath);

            FileInfo fileInfo = GetFileInfo(sFilePath);
            ForceDeleteFile(sTargetPath);
            fileInfo.MoveTo(sTargetPath);
        }

        public static bool CheckFileExist(this string sFilePath)
        {
            FileInfo fileInfo = new FileInfo(sFilePath);
            return fileInfo.Exists;
        }

        public static bool CheckDirectoryExist(this string sFilePath)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(sFilePath);
            return directoryInfo.Exists;
        }

        public static List<FileInfo> GetFiles(this string sFolderPath)
        {
            List<FileInfo> lstReturn = new List<FileInfo>();

            DirectoryInfo directoryInfo = new DirectoryInfo(sFolderPath);

            DirectoryInfo[] directories = directoryInfo.GetDirectories();

            if (directoryInfo.Exists == false)
            {
                directoryInfo.Create();
            }
            else
            {
                lstReturn.AddRange(GetFiles(directoryInfo));
            }

            return lstReturn;
        }

        public static List<FileInfo> GetFiles(DirectoryInfo directoryInfo)
        {
            List<FileInfo> lstReturn = new List<FileInfo>();
            List<DirectoryInfo> directories = directoryInfo.GetDirectories().ToList();

            lstReturn.AddRange(directoryInfo.GetFiles().ToList());

            foreach (DirectoryInfo info in directories)
            {
                lstReturn.AddRange(GetFiles(info));
            }

            return lstReturn;
        }

        #region 找尋檔案系列

        public static List<FileInfo> FindFiles(this string sFolderPath, string sFindWording)
        {
            List<FileInfo> files = GetFiles(sFolderPath);
            return files.Where(s => s.FullName.IndexOf(sFindWording) != -1).ToList();
        }

        public static FileInfo FindFile(this string sFolderPath, string sFindWording)
        {
            List<FileInfo> files = GetFiles(sFolderPath);
            return files.Where(s => s.FullName.IndexOf(sFindWording) != -1).FirstOrDefault();
        }

        public static FileInfo FindFileByExtension(this string sFolderPath, string sExtension)
        {
            return sFolderPath.FindFilesByExtension(sExtension).FirstOrDefault();
        }

        public static List<FileInfo> FindFilesByExtension(this string sFolderPath, string sExtension)
        {
            List<FileInfo> files = GetFiles(sFolderPath);
            return files.Where(s => s.Extension.ToLower().Equals(sExtension.ToLower())).ToList();
        }

        #endregion


        public static string GetContentType(string sFileName)
        {
            string sDefaultType = "application/unknown";
            RegistryKey rkRegkey;
            RegistryKey rkFileextkey;
            string sFileContentType;
            string sExtension = Path.GetExtension(sFileName);

            try
            {
                //look in HKCR
                rkRegkey = Registry.ClassesRoot;

                //look for extension
                rkFileextkey = rkRegkey.OpenSubKey(sExtension);

                //retrieve Content Type value
                sFileContentType = rkFileextkey.GetValue("Content Type", sDefaultType).ToString();

                //cleanup
                rkRegkey = null;
                rkFileextkey = null;
            }
            catch
            {
                sFileContentType = sDefaultType;
            }

            return sFileContentType;
        }

        public static bool PathEqual(this FileInfo fileInfo, string sTargetFilePath)
        {
            string sFilePath = fileInfo.FullName;

            return PathEqual(sFilePath, sTargetFilePath);
        }

        public static bool PathEqual(this string sFilePath, string sTargetFilePath)
        {
            if (sFilePath == sTargetFilePath)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 無論如何強制刪除指定路徑的檔案
        /// </summary>
        /// <param name="sFilePath">File Path</param>
        private static void ForceDeleteFile(string sFilePath)
        {
            if (File.Exists(sFilePath))
            {
                if ((File.GetAttributes(sFilePath) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                {
                    File.SetAttributes(sFilePath, FileAttributes.Normal);
                }
                File.Delete(sFilePath);
            }
        }

        public static void Delete(string sFilePath)
        {
            FileInfo info = GetFileInfo(sFilePath);
            Delete(info);
        }

        public static void Delete(FileInfo info)
        {
            ForceDeleteFile(info.FullName);
        }

        public static void Delete(List<FileInfo> lstFile)
        {
            foreach (FileInfo info in lstFile)
            {
                Delete(info);
            }
        }

        #endregion

        public static string GetContent(this string sFilePath)
        {
            string sReturn = string.Empty;

            FileInfo info = sFilePath.GetFileInfo();

            StreamReader openText = info.OpenText();
            sReturn = openText.ReadToEnd();
            openText.Close();

            return sReturn;
        }

        public static void SaveContent(this string sFilePath, string sContent)
        {
            FileInfo info = sFilePath.GetFileInfo();

            StreamWriter streamWriter = info.CreateText();
            streamWriter.Write(sContent);

            streamWriter.Close();
        }

        public static string GetExtension(this string sFilePath)
        {
            string extension = Path.GetExtension(sFilePath);

            //移掉前面的.
            return extension.Remove(0, 1);
        }
    }
}
